/**
 * 工具类 - 文件上传相关方法
 * 包含获取预签名URL和上传到阿里云OSS的功能
 */

import Request from '../utils/request.js'

/**
 * 生成随机四位数字
 * @returns {string} 四位随机数字字符串
 */
function generateRandomNumber() {
  return Math.floor(1000 + Math.random() * 9000).toString()
}

/**
 * 获取文件扩展名
 * @param {string} fileName 文件名
 * @returns {string} 文件扩展名（不含点）
 */
function getFileExtension(fileName) {
  return fileName.split('.').pop().toLowerCase()
}

/**
 * 根据文件扩展名获取MIME类型
 * @param {string} extension 文件扩展名
 * @returns {string} MIME类型
 */
function getMimeType(extension) {
  const mimeTypes = {
    'jpg': 'image/jpeg',
    'jpeg': 'image/jpeg',
    'png': 'image/png',
    'gif': 'image/gif',
    'webp': 'image/webp',
    'bmp': 'image/bmp',
    'pdf': 'application/pdf',
    'doc': 'application/msword',
    'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
    'xls': 'application/vnd.ms-excel',
    'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    'txt': 'text/plain'
  }
  return mimeTypes[extension] || 'application/octet-stream'
}

/**
 * 验证文件是否为图片类型
 * @param {string} fileName 文件名
 * @returns {boolean} 是否为图片文件
 */
function isImageFile(fileName) {
  const extension = getFileExtension(fileName).toLowerCase()
  const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp']
  return imageExtensions.includes(extension)
}

/**
 * 验证文件大小是否符合要求
 * @param {number} fileSize 文件大小（字节）
 * @param {number} maxSize 最大文件大小（MB），默认5MB
 * @returns {boolean} 文件大小是否符合要求
 */
function validateFileSize(fileSize, maxSize = 5) {
  const maxSizeInBytes = maxSize * 1024 * 1024 // 转换为字节
  return fileSize <= maxSizeInBytes
}

/**
 * 生成文件名（包含路径）
 * @param {string} moduleName 模块名称（如：pile）
 * @param {string} originalFileName 原始文件名
 * @param {string} prefix 文件前缀（如：avatar）
 * @returns {string} 完整的文件路径名
 */
function generateFileName(moduleName, originalFileName, prefix = 'file') {
  const extension = getFileExtension(originalFileName)
  const currentDate = new Date().toISOString().slice(0, 10).replace(/-/g, '')
  const randomNumber = generateRandomNumber()
  
  return `${moduleName}/${currentDate}/${prefix}${randomNumber}.${extension}`
}

/**
 * 获取预签名URL
 * @param {string} fileName 文件名（包含路径）
 * @param {string} fileType MIME类型
 * @returns {Promise<string>} 预签名URL
 */
async function getPresignedUrl(fileName, fileType) {
  try {
    const response = await Request.get('/api/oss/upload/presigned-url', {
      fileName: fileName,
      fileType: fileType
    })
    
    // console.log('获取预签名URL成功:', response)
    return response
  } catch (error) {
    console.error('获取预签名URL失败:', error)
    throw error
  }
}

/**
 * 上传文件到阿里云OSS
 * @param {string} filePath 本地文件路径
 * @param {string} presignedUrl 预签名URL
 * @param {string} fileType MIME类型
 * @param {Function} onProgress 上传进度回调函数
 * @returns {Promise<string>} 上传成功后的文件URL
 */
async function uploadToOSS(filePath, presignedUrl, fileType, onProgress) {
  return new Promise((resolve, reject) => {
    console.log('开始上传到OSS:', {
      filePath,
      presignedUrl,
      fileType
    })
    
    // 解析预签名URL以获取更多信息
    // try {
    //   const url = new URL(presignedUrl)
    //   console.log('预签名URL解析:', {
    //     host: url.host,
    //     pathname: url.pathname,
    //     searchParams: Object.fromEntries(url.searchParams)
    //   })
    // } catch (e) {
    //   console.error('预签名URL格式错误:', e)
    // }
    
    // 使用PUT方法上传到OSS
    // 由于uni.uploadFile默认使用POST方法，我们需要使用uni.request来实现PUT上传
    
    // 首先读取文件内容
    uni.getFileSystemManager().readFile({
      filePath: filePath,
      success: (fileRes) => {
        console.log('文件读取成功，开始PUT上传')
        
        // 使用uni.request发送PUT请求
        uni.request({
          url: presignedUrl,
          method: 'PUT',
          data: fileRes.data,
          header: {
            'Content-Type': fileType
          },
          success: (res) => {
            console.log('OSS上传响应详情:', {
              statusCode: res.statusCode,
              data: res.data,
              header: res.header
            })
            
            if (res.statusCode === 200 || res.statusCode === 204) {
              // 上传成功，返回文件的访问URL
              // 通常OSS上传成功后，文件URL就是预签名URL去掉查询参数的部分
              const fileUrl = presignedUrl.split('?')[0]
              console.log('上传成功，文件URL:', fileUrl)
              resolve(fileUrl)
            } else {
              // 解析错误信息
              let errorMessage = `上传失败，状态码: ${res.statusCode}`
              
              if (res.statusCode === 404) {
                errorMessage = '上传失败: 资源未找到(404)，可能是Bucket不存在或预签名URL无效'
              } else if (res.statusCode === 403) {
                errorMessage = '上传失败: 权限不足(403)，请检查OSS权限配置'
              } else if (res.statusCode === 400) {
                errorMessage = '上传失败: 请求参数错误(400)'
              }
              
              // 尝试解析XML错误信息
              if (res.data && typeof res.data === 'string' && res.data.includes('<Error>')) {
                try {
                  const codeMatch = res.data.match(/<Code>(.*?)<\/Code>/)
                  const messageMatch = res.data.match(/<Message>(.*?)<\/Message>/)
                  if (codeMatch && messageMatch) {
                    errorMessage += `\nOSS错误: ${codeMatch[1]} - ${messageMatch[1]}`
                  }
                } catch (e) {
                  console.error('解析OSS错误信息失败:', e)
                }
              }
              
              console.error('上传失败详情:', errorMessage)
              console.error('完整响应数据:', res.data)
              reject(new Error(errorMessage))
            }
          },
          fail: (err) => {
            console.error('上传请求失败:', err)
            reject(new Error(`上传请求失败: ${err.errMsg || err.message || '未知错误'}`))
          }
        })
      },
      fail: (err) => {
        console.error('文件读取失败:', err)
        reject(new Error(`文件读取失败: ${err.errMsg || err.message || '未知错误'}`))
      }
    })
  })
}

/**
 * 完整的文件上传流程
 * @param {string} filePath 本地文件路径
 * @param {string} moduleName 模块名称
 * @param {string} originalFileName 原始文件名
 * @param {string} prefix 文件前缀
 * @param {Function} onProgress 上传进度回调函数
 * @param {boolean} imageOnly 是否只允许上传图片，默认false
 * @param {number} maxSize 最大文件大小（MB），默认5MB
 * @returns {Promise<Object>} 包含文件URL和文件名的对象
 */
async function uploadFile(filePath, moduleName = 'pile', originalFileName = 'image.jpg', prefix = 'avatar', onProgress, imageOnly = false, maxSize = 5) {
  try {
    // 1. 如果启用了图片限制，验证文件类型
    if (imageOnly && !isImageFile(originalFileName)) {
      throw new Error('只能上传图片文件（jpg、jpeg、png、gif、webp、bmp）')
    }
    
    // 2. 获取文件信息（如果可能的话）
    // 注意：在uni-app中，从chooseImage获取的文件路径可能无法直接获取文件大小
    // 这里主要依赖前端选择时的限制
    
    // 3. 生成文件名
    const fileName = generateFileName(moduleName, originalFileName, prefix)
    
    // 4. 获取文件类型
    const extension = getFileExtension(originalFileName)
    const fileType = getMimeType(extension)
    
    // 5. 获取预签名URL
    const presignedUrl = await getPresignedUrl(fileName, fileType)
    
    // 6. 上传文件到OSS
    const fileUrl = await uploadToOSS(filePath, presignedUrl, fileType, onProgress)
    
    return {
      url: fileUrl,
      fileName: fileName,
      originalName: originalFileName
    }
  } catch (error) {
    console.error('文件上传失败:', error)
    throw error
  }
}

/**
 * 批量上传文件
 * @param {Array} files 文件数组，每个元素包含 {filePath, originalFileName, prefix}
 * @param {string} moduleName 模块名称
 * @param {Function} onProgress 整体进度回调函数
 * @returns {Promise<Array>} 上传结果数组
 */
async function batchUploadFiles(files, moduleName = 'pile', onProgress) {
  const results = []
  const total = files.length
  
  for (let i = 0; i < files.length; i++) {
    const file = files[i]
    try {
      const result = await uploadFile(
        file.filePath,
        moduleName,
        file.originalFileName,
        file.prefix,
        (progress) => {
          // 计算整体进度
          const overallProgress = Math.floor(((i + progress / 100) / total) * 100)
          if (onProgress) {
            onProgress(overallProgress, i + 1, total)
          }
        }
      )
      results.push({
        success: true,
        ...result
      })
    } catch (error) {
      results.push({
        success: false,
        error: error.message,
        originalName: file.originalFileName
      })
    }
  }
  
  return results
}

// 默认导出 request 函数（用于兼容现有代码）
const request = (options) => {
  return Request.request(options)
}

export default request

export {
  uploadFile,
  batchUploadFiles,
  getPresignedUrl,
  uploadToOSS,
  generateFileName,
  getMimeType,
  getFileExtension,
  generateRandomNumber,
  isImageFile,
  validateFileSize
}